﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;

namespace EnvRide.Core.ObjectModel
{
    public static class XmlUtils
    {
        /// <summary>
        /// Returns the full path of the supplied node instance.
        /// </summary>
        /// <param name="node">Node instance to retrieve the full path.</param>
        /// <returns>Full path of the supplied node instance.</returns>
        public static string GetFullPath(XmlNode node)
        {
            if (node == null)
                throw new ArgumentNullException("node");

            String fullPath = null;

            if (node == node.OwnerDocument.DocumentElement)
            {
                fullPath = "/" + node.Name;
            }
            else
            {
                List<XmlNode> nodesToRoot = new List<XmlNode>();

                XmlNode currentNode = node;

                if (node is XmlAttribute)
                {
                    // If the supplied node its an attribute, then it should also process the owner element
                    nodesToRoot.Add(node);
                    currentNode = ((XmlAttribute)node).OwnerElement;
                }
                   
                do
                {
                    // Adds all the nodes from the current to the root
                    nodesToRoot.Add(currentNode);

                    currentNode = currentNode.ParentNode;
                }
                while (currentNode != null && currentNode != node.OwnerDocument);

                StringBuilder sb = new StringBuilder();

                for (int i = nodesToRoot.Count() - 1; i >= 0; i--)
                {
                    currentNode = nodesToRoot[i];

                    // Writes the separator char
                    sb.Append("/");

                    if (currentNode.NodeType == XmlNodeType.Attribute)
                    {
                        // If its an attribute, writes the "at" char
                        sb.Append("@");
                    }

                    sb.Append(currentNode.Name);

                    if (currentNode.ParentNode != currentNode.OwnerDocument && currentNode is XmlElement)
                    { 
                        // If its not the root element, writes the position of the current node
                        for (int j = 0; j < currentNode.ParentNode.ChildNodes.Count; j++)
                        {
                            XmlNode child = currentNode.ParentNode.ChildNodes.Item(j);

                            if (child == currentNode)
                            {
                                sb.Append("[");
                                sb.Append(j);
                                sb.Append("]");

                                break;
                            }
                        }
                    }
                }

                fullPath = sb.ToString();
            }

            return fullPath;
        }
    }
}
